package com.qfedu.aunt.commons.service.impl;

import com.alibaba.druid.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qfedu.aunt.commons.dto.AdminDTO;
import com.qfedu.aunt.commons.exception.BusinessException;
import com.qfedu.aunt.commons.mapper.UserMapper;
import com.qfedu.aunt.commons.mapper.UserRoleMapper;
import com.qfedu.aunt.commons.pojo.Admin;
import com.qfedu.aunt.commons.mapper.AdminMapper;
import com.qfedu.aunt.commons.pojo.Role;
import com.qfedu.aunt.commons.pojo.User;
import com.qfedu.aunt.commons.pojo.UserRole;
import com.qfedu.aunt.commons.result.ResponseCode;
import com.qfedu.aunt.commons.service.AdminService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qfedu.aunt.commons.utils.MD5;
import com.qfedu.aunt.commons.vo.AdminAddVo;
import com.qfedu.aunt.commons.vo.AdminQueryVo;
import com.qfedu.aunt.commons.vo.AdminUpdateVo;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author xiaobobo
 * @since 2022-10-31
 */
@Service
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements AdminService {

    @Autowired
    private AdminMapper adminMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Override
    public IPage<AdminDTO> findAdminByPage(Integer currentPage, Integer pageSize) {
        if(currentPage==null||null==pageSize){
           throw new BusinessException(ResponseCode.PARAMETER_ERROR.getCode(),
                   ResponseCode.PARAMETER_ERROR.getMessage());
        }
        //程序执行到这里说明 参数是对的
        Page<Admin> page=new Page<>();
        page.setCurrent(currentPage);
        page.setSize(pageSize);

        //直接查询
        IPage<Admin> adminIPage = adminMapper.selectPage(page, null);
        //这里面还差东西 账户 和 密码
        long total = adminIPage.getTotal();
        List<Admin> records = adminIPage.getRecords();

        //申明存放数据的最终集合
        List<AdminDTO> adminDTOS=new ArrayList<>();

        records.stream().forEach(admin->{
            //一次遍历都能获取到 这个对象
            //首先copy对象
            AdminDTO adminDTO = new AdminDTO();
            try {
                BeanUtils.copyProperties(adminDTO,admin);
               //接下来还要查询我们用户数据
                String userId = admin.getUserId();
                //接下来通过id查询用户数据

                QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
                userQueryWrapper.eq("user_id",userId);

                User user = userMapper.selectOne(userQueryWrapper);
                //接下来将用户中的属性Copy进去
                BeanUtils.copyProperties(adminDTO,user);
                //最终将这个数据返回切
                adminDTOS.add(adminDTO);

                //查询用户所属的角色 以及角色的名字
                List<Role> roles=userMapper.findRolesByUserId(userId);

                String roleString=getRoleString(roles);
                adminDTO.setStringRoles(roleString);
                
                List<String> roleSelectList=getRoleIdList(roles);
                adminDTO.setRoleSelectList(roleSelectList);

                adminDTO.setRoleList(roles);

            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        IPage<AdminDTO> adminDTOIPage=new Page<>();
        adminDTOIPage.setRecords(adminDTOS);
        adminDTOIPage.setTotal(total);

        return adminDTOIPage;
    }

    /**
     * 将role的id弄成List集合
     * @param roles
     * @return
     */
    private List<String> getRoleIdList(List<Role> roles) {
        List<String> roleIdList=new ArrayList<>();
        roles.stream().forEach(role -> {
            roleIdList.add(role.getRoleId());
        });
        return roleIdList;
    }

    /**
     * 获取所有的角色的字符串
     * @param roles
     * @return
     */
    private String getRoleString(List<Role> roles) {
        StringBuffer stringBuffer=new StringBuffer();
        roles.stream().forEach(role -> {
            stringBuffer.append(role.getRoleName()+"|");
        });
        //最后多了一个|
        String s = stringBuffer.toString();
        String substring = s.substring(0, s.lastIndexOf("|"));
        return substring;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteById(String adminId) {
        if(StringUtils.isEmpty(adminId)){
            throw new BusinessException(
                    ResponseCode.PARAMETER_ERROR.getCode(),
                    ResponseCode.PARAMETER_ERROR.getMessage());
        }
        //接下来我们就可以执行业务了
        //首先通过id去查询数据
        Admin admin = adminMapper.selectById(adminId);
        if(null!=admin){
            //说明查询到数据了
            //首先获取这里的用户id
            String userId = admin.getUserId();
            //然后删除admin的数据
            adminMapper.deleteById(adminId);
            //然后查询用户

            User user = userMapper.selectById(userId);
            if(null!=user) {
                userMapper.deleteById(userId);
            }
            //这里在进行删除数据的时候没有删除中间表的数据 所以这里还需要删除中间表的数据
            //这里还要通过用户id删除中间表的数据

            UpdateWrapper<UserRole> userRoleUpdateWrapper = new UpdateWrapper<>();
            userRoleUpdateWrapper.eq("user_id",userId);
            //接下来实施删除
            userRoleMapper.delete(userRoleUpdateWrapper);

            return ;
        }
        //如果程序执行到这里 说明传递来的这个id是有问题的
        throw new BusinessException(
                ResponseCode.ADMIN_EXCEPTION.getCode(),
                ResponseCode.ADMIN_EXCEPTION.getMessage());
    }

    @Override
    public void deleteByIds(String adminIds) {
        if(StringUtils.isEmpty(adminIds)){
            throw new BusinessException(
                    ResponseCode.PARAMETER_ERROR.getCode(),
                    ResponseCode.PARAMETER_ERROR.getMessage());
        }
        if(adminIds.endsWith(",")){
            adminIds=adminIds.substring(0,adminIds.lastIndexOf(","));
        }
        //执行到这里说明我们的最后的,已经去掉了
        if(!adminIds.contains(",")){
            deleteById(adminIds);
            return;
        }
        //程序执行到这里说明传递了多个id
        String[] split = adminIds.split(",");
        for (String adminId:split) {
            deleteById(adminId);
        }
    }

    @Override
    public IPage<AdminDTO> findAdminByCondition(AdminQueryVo adminQueryVo,Integer currentPage,Integer pageSize) throws InvocationTargetException, IllegalAccessException {
        //这里还要对我们的参数进行判断
        if(currentPage==null||pageSize==null){
             throw new BusinessException(ResponseCode.PARAMETER_ERROR.getCode(),
                     ResponseCode.PARAMETER_ERROR.getMessage());
        }
        //接下来执行到这里
        if(StringUtils.isEmpty(adminQueryVo.getAdminName())&&
           StringUtils.isEmpty(adminQueryVo.getUsername())){
            //这里说明没有传递参数过来
            //直接查询所有数据进行分页
           return  findAdminByPage(currentPage,pageSize);
        }
        //程序执行到这里我们要更具条件进行判断
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        List<AdminDTO> adminDTOS=new ArrayList<>();
        if(!StringUtils.isEmpty(adminQueryVo.getUsername())
                &&StringUtils.isEmpty(adminQueryVo.getAdminName())){
            //这里专门用来处理UserLike的数据
            handlerUserLike(adminQueryVo, userQueryWrapper, adminDTOS);
        }else if(StringUtils.isEmpty(adminQueryVo.getUsername())
                &&!StringUtils.isEmpty(adminQueryVo.getAdminName())){
            //这里是处理AdminNameLike
            handlerAdminNameLike(adminQueryVo, adminDTOS);
        }else{
            //说明username有值、并且 adminName也有值
            handlerAdminNameLike(adminQueryVo, adminDTOS);
            //然后通过user的like查询数据
            //这里说明需要构建的是我们的username的模糊查询
            handlerUserLike(adminQueryVo, userQueryWrapper, adminDTOS);
        }
        //接下来这个分页? 在这里在数据库中分页这个就不靠谱了
        //可以实现代码来实现这个数据  或者直接将数据放到前端去 让前端自己去分离这个数据
        //真实查询出来的数据
        int size = adminDTOS.size();
        //计算取数据的开始位置
        int startIndex=(currentPage-1)*pageSize;
        //处理数据的问题
        List<AdminDTO> adminDTOList1=getData(startIndex,pageSize,adminDTOS);

        IPage<AdminDTO> adminDTOIPage=new Page<>();
        adminDTOIPage.setRecords(adminDTOList1);
        adminDTOIPage.setTotal(size);

        return adminDTOIPage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addAdmin(MultipartFile file, AdminAddVo adminAddVo) throws InvocationTargetException, IllegalAccessException {
        if(null==file||adminAddVo.getSex()==null
           || StringUtils.isEmpty(adminAddVo.getAdminName())
           || StringUtils.isEmpty(adminAddVo.getPassword())
           || StringUtils.isEmpty(adminAddVo.getRoleId())
           || StringUtils.isEmpty(adminAddVo.getTelPhone())
           || StringUtils.isEmpty(adminAddVo.getUsername())){
            throw new BusinessException(ResponseCode.PARAMETER_ERROR.getCode(),
                    ResponseCode.PARAMETER_ERROR.getMessage());
        }
        //执行到这里 需要分开业务来执行
        //第一步：向User表添加数据
        User user = new User();
        user.setLastLoginTime(new Date());
        //这里首先要将前端传递过来的密码进行散列
        String encryptPassword = MD5.encrypt(adminAddVo.getPassword());
        BeanUtils.copyProperties(user,adminAddVo);
        user.setPassword(encryptPassword);

        //添加数据到User表
        userMapper.insert(user);
        //接下来要获取id值
        Admin admin = new Admin();
        admin.setUserId(user.getUserId());
        BeanUtils.copyProperties(admin,adminAddVo);
        //TODO ：将用户头像存储到第三方CDN上(阿里云的OSS)


        //添加数据
        adminMapper.insert(admin);
        //接下来玩中间表(用户角色那个中间表)
        //构建中间表的数据
        UserRole userRole = new UserRole();
        userRole.setUserId(user.getUserId());
        userRole.setRoleId(adminAddVo.getRoleId());
        //添加数据到中间表
        userRoleMapper.insert(userRole);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAdmin(AdminUpdateVo adminUpdateVo) throws Exception {
         if(null==adminUpdateVo||
                 adminUpdateVo.getSex()==null||
            StringUtils.isEmpty(adminUpdateVo.getUsername())||
            StringUtils.isEmpty(adminUpdateVo.getAdminName())||
            StringUtils.isEmpty(adminUpdateVo.getTelPhone())||
            StringUtils.isEmpty(adminUpdateVo.getAdminId())||
            StringUtils.isEmpty(adminUpdateVo.getUserId())||
            adminUpdateVo.getRoleSelectList()==null||
            adminUpdateVo.getRoleSelectList().size()==0){
             throw new BusinessException(ResponseCode.PARAMETER_ERROR.getCode(),
                     ResponseCode.PARAMETER_ERROR.getMessage());
         }
         //执行到这里参数没有问题
        //接下来我们就要可似乎更新数据了...
        Admin admin = new Admin();
         //将数据COPY到上面
        BeanUtils.copyProperties(admin,adminUpdateVo);
        //接下来更新数据
        adminMapper.updateById(admin);

        //接下来再将这个数据COPY到user
        User user = new User();
        BeanUtils.copyProperties(user,adminUpdateVo);
        //接下来更新数据
        userMapper.updateById(user);

        //接下来还要去更新中间表的数据
        //先删除数据 再更新数据
        UpdateWrapper<UserRole> userRoleUpdateWrapper = new UpdateWrapper<>();
        userRoleUpdateWrapper.eq("user_id",adminUpdateVo.getUserId());
        //接下来就是更新数据
        userRoleMapper.delete(userRoleUpdateWrapper);
        
        //接下来从新插入新的映射关系(用户和角色的映射关系)
        List<String> roleSelectList = adminUpdateVo.getRoleSelectList();
        for (String roleId:roleSelectList) {
            //接下来开始组合我们的值
            UserRole userRole = new UserRole();
            userRole.setRoleId(roleId);
            userRole.setUserId(adminUpdateVo.getUserId());
            //添加数据
            userRoleMapper.insert(userRole);
        }
        //整个逻辑运行到这里没有问题的话 那么说民这个这个结果就没有问题
    }

    /**
     * 通过下标计算出应该取数据的这个位置
     * @param startIndex
     * @param pageSize
     * @param adminDTOS
     * @return
     */
    private List<AdminDTO> getData(int startIndex, Integer pageSize, List<AdminDTO> adminDTOS) {
        //申明一个存放数据的容器
        List<AdminDTO> adminDTOList2=new ArrayList<>();
        for (int i = startIndex; i <adminDTOS.size() ; i++) {
            adminDTOList2.add(adminDTOS.get(i));
        }
        return adminDTOList2;
    }

    /**
     * 这里是处理AdminNameLike数据
     * @param adminQueryVo
     * @param adminDTOS
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    private void handlerAdminNameLike(AdminQueryVo adminQueryVo, List<AdminDTO> adminDTOS) throws IllegalAccessException, InvocationTargetException {
        //这种情况表示的是通过adminName去进行查询

        QueryWrapper<Admin> adminQueryWrapper = new QueryWrapper<>();
        adminQueryWrapper.like("admin_name", adminQueryVo.getAdminName());
        //接下来进行查询
        List<Admin> admins = adminMapper.selectList(adminQueryWrapper);
        for (Admin admin1 : admins) {
            //首先将这个admin的数据进行封装
            AdminDTO adminDTO = new AdminDTO();
            BeanUtils.copyProperties(adminDTO, admin1);
            //接下来获取用户id
            String userId = admin1.getUserId();
            //接下来通过用户id获取数据
            User user = userMapper.selectById(userId);
            //接下来代码进行封装
            BeanUtils.copyProperties(adminDTO, user);
            //接下来将这个数据放到我们的集合中去
            adminDTOS.add(adminDTO);
        }
    }

    /**
     * 这里是处理UserNameLike的数据
     * @param adminQueryVo
     * @param userQueryWrapper
     * @param adminDTOS
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    private void handlerUserLike(AdminQueryVo adminQueryVo, QueryWrapper<User> userQueryWrapper, List<AdminDTO> adminDTOS) throws IllegalAccessException, InvocationTargetException {
        //这里说明需要构建的是我们的username的模糊查询
        userQueryWrapper.like("username", adminQueryVo.getUsername());
        //接下来查询我们的用户数据
        List<User> users = userMapper.selectList(userQueryWrapper);
        //接下来遍历这个用户数据
        for (User u : users) {
            //构建了这个条件之后 先查询用户表
            AdminDTO adminDTO = new AdminDTO();
            //将用户对象中的数据封装到adminDTO中
            BeanUtils.copyProperties(adminDTO, u);
            //通过用户id查询admin的数据
            String userId = u.getUserId();
            QueryWrapper<Admin> adminQueryWrapper = new QueryWrapper<>();
            adminQueryWrapper.eq("user_id", userId);
            //接下来就是查询
            Admin admin = adminMapper.selectOne(adminQueryWrapper);
            //接下来将这个admin的数据封装到 dto中
            BeanUtils.copyProperties(adminDTO, admin);
            //将这个对象放到容器中
            adminDTOS.add(adminDTO);
        }
    }
}
